package com.cobo.fitness.web.fitness.routes;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.cobo.common.core.Page;
import com.cobo.common.core.R;
import com.cobo.fitness.core.constant.FitnessIndexConst;
import com.cobo.fitness.core.meillisearch.MeilsearchEngine;
import com.cobo.fitness.web.fitness.entity.Exercise;
import com.cobo.fitness.web.fitness.services.ExerciseService;
import com.cobo.fitness.web.fitness.services.InstructionService;
import com.cobo.fitness.web.fitness.services.SearchService;
import com.cobo.fitness.web.fitness.services.SecondaryMucleService;
import com.cobo.fitness.web.fitness.vo.ExerciseResVo;
import com.meilisearch.sdk.model.SearchResult;
import com.meilisearch.sdk.model.Searchable;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/exercises")
public class FitnessController {

    @Autowired
    private ExerciseService exerciseService;

    @Autowired
    private InstructionService instructionService;

    @Autowired
    private SecondaryMucleService secondaryMucleService;

    @Autowired
    private SearchService searchService;

    @Autowired
    private MeilsearchEngine meilsearchEngine;

    @GetMapping("/sync")
    public R sync() {
        searchService.sync();
        return R.ok();
    }

    @GetMapping("/query")
    public R query(@RequestParam String name) {
        meilsearchEngine.search(FitnessIndexConst.FITNESS, name,1,10);
        return R.ok();
    }

    @GetMapping("/bodyPartList")
    public R<String[]> bodyPartList() {
        return R.ok(new String[]{
                "back",
                "cardio",
                "chest",
                "lower arms",
                "lower legs",
                "neck",
                "shoulders",
                "upper arms",
                "upper legs",
                "waist"
        });

    }

    @GetMapping("/list")
    public List<ExerciseResVo> exercise(@RequestParam(required = false,defaultValue = "10") Integer limit,
                                        @RequestParam(required = false,defaultValue = "0")Integer offset,
                                        @RequestParam(required = false,defaultValue="") String bodyPart,
                                        @RequestParam(required = false,defaultValue="") String equipment
    ) {
        LambdaQueryChainWrapper<Exercise> exerciseLambdaQueryChainWrapper = exerciseService.lambdaQuery();
        if (StringUtils.isNotBlank(bodyPart)) {
            exerciseLambdaQueryChainWrapper.eq(Exercise::getBodyPart, bodyPart);
        }
        if (StringUtils.isNotBlank(equipment)) {
            exerciseLambdaQueryChainWrapper.eq(Exercise::getEquipment, equipment);
        }
        List<Exercise> exercises =
                exerciseLambdaQueryChainWrapper
                .last("limit " + offset + "," + limit)
                .list();

        return exercises.stream().map(exerciseService::transformToRes).collect(Collectors.toList());
    }

    @GetMapping("/bodyPart/{bodyPart}")
    public R<Page<ExerciseResVo>> bodyPart(@PathVariable("bodyPart") String bodyPart,
                                        @RequestParam(value = "searchVal",required = false) String searchVal,
                                        @RequestParam(required = false,defaultValue = "10") Integer limit,
                                        @RequestParam(required = false,defaultValue = "0")Integer offset) {
//        if (StringUtils.isEmpty(searchVal)){
//            LambdaQueryChainWrapper<Exercise> wrapper = exerciseService.lambdaQuery();
//            if (!StringUtils.equals(bodyPart, "所有")) {
//                wrapper.eq(Exercise::getBodyPart, bodyPart);
//            }
//
//            List<Exercise> exercises = new ArrayList<>();
//            if (offset == -1) {
//                exercises = wrapper.list();
//            }else {
//                exercises   = wrapper
//                        .last("limit " + offset + "," +limit)
//                        .list();
//            }
//            wrapper = exerciseService.lambdaQuery();
//            long totalSize = 0;
//            if (!StringUtils.equals(bodyPart, "所有")) {
//                totalSize = wrapper
//                        .eq(Exercise::getBodyPart, bodyPart).count();
//            }else {
//                totalSize = wrapper.count();
//            }
//
//            return Page.wrapper(totalSize, exercises.stream().map(exerciseService::transformToRes).collect(Collectors.toList()));
//        }else {
//
//        }
//          .setFilter(new String[] {"id > 1 AND genres = Action"})
        String[] filter = new String[]{};
        if (!StringUtils.equals(bodyPart, "所有")) {
            filter = new String[]{"bodyPart = \"" + bodyPart+"\""};
        }
        Searchable search = meilsearchEngine.search(FitnessIndexConst.FITNESS, searchVal,filter, offset, limit);
        if (search instanceof SearchResult) {
            SearchResult sr = (SearchResult) search;
            int estimatedTotalHits = sr.getEstimatedTotalHits();
            ArrayList<HashMap<String, Object>> hits = sr.getHits();
            List<Exercise> exercises = JSON.parseObject(JSON.toJSONString(hits), new TypeReference<List<Exercise>>() {
            }.getType());
            return Page.wrapper(estimatedTotalHits, exercises.stream().map(exerciseService::transformToRes).collect(Collectors.toList()));
        }
        return R.ok();
    }

    @GetMapping("/equipment/{type}")
    public List<ExerciseResVo> equipment(@PathVariable("type") String type,
                                        @RequestParam(required = false,defaultValue = "10") Integer limit,
                                        @RequestParam(required = false,defaultValue = "0")Integer offset) {

        List<Exercise> exercises = exerciseService.lambdaQuery()
                .eq(Exercise::getEquipment, type)
                .last("limit " + offset + "," + limit)
                .list();

        return exercises.stream().map(exerciseService::transformToRes).collect(Collectors.toList());
    }

    @GetMapping("/target/{target}")
    public List<ExerciseResVo> target(@PathVariable("target") String target,
                                         @RequestParam(required = false,defaultValue = "10") Integer limit,
                                         @RequestParam(required = false,defaultValue = "0")Integer offset) {

        List<Exercise> exercises = exerciseService.lambdaQuery()
                .eq(Exercise::getTarget, target)
                .last("limit " + offset + "," + limit)
                .list();

        return exercises.stream().map(exerciseService::transformToRes).collect(Collectors.toList());
    }

    @GetMapping("/exercise/{id}")
    public ExerciseResVo findOne(@PathVariable("id") String id) {
        Exercise exercise = exerciseService.lambdaQuery()
                .eq(Exercise::getId, id)
                .one();

        return exerciseService.transformToRes(exercise);
    }

    @GetMapping("/name/{name}")
    public List<ExerciseResVo> findByName(@PathVariable("name") String name,
                                          @RequestParam(required = false,defaultValue = "10") Integer limit,
                                          @RequestParam(required = false,defaultValue = "0")Integer offset) {

        List<Exercise> exercises = exerciseService.lambdaQuery()
                .eq(Exercise::getName, name)
                .last("limit " + offset + "," + limit)
                .list();

        return exercises.stream().map(exerciseService::transformToRes).collect(Collectors.toList());
    }


    @GetMapping("/equipmentList")
    public String[] equipmentList() {
        return
                new String[]{
                        "assisted",
                        "band",
                        "barbell",
                        "body weight",
                        "bosu ball",
                        "cable",
                        "dumbbell",
                        "elliptical machine",
                        "ez barbell",
                        "hammer",
                        "kettlebell",
                        "leverage machine",
                        "medicine ball",
                        "olympic barbell",
                        "resistance band",
                        "roller",
                        "rope",
                        "skierg machine",
                        "sled machine",
                        "smith machine",
                        "stability ball",
                        "stationary bike",
                        "stepmill machine",
                        "tire",
                        "trap bar",
                        "upper body ergometer",
                        "weighted",
                        "wheel roller",
                };
    }

    @GetMapping("/targetList")
    public String[] targetList() {
        return
                new String[]{
                        "abductors",
                        "abs",
                        "adductors",
                        "biceps",
                        "calves",
                        "cardiovascular system",
                        "delts",
                        "forearms",
                        "glutes",
                        "hamstrings",
                        "lats",
                        "levator scapulae",
                        "pectorals",
                        "quads",
                        "serratus anterior",
                        "spine",
                        "traps",
                        "triceps",
                        "upper back"
                };
    }

    @GetMapping("/init")
    public boolean listFile()throws Exception {
//        String baseFp = "D://fitness";
//        String regex = "exercises.*txt";
//        File file = new File(baseFp);
//        for (File listFile : file.listFiles()) {
//            if (listFile.isFile()) {
//                boolean matches = Pattern.matches(regex, listFile.getName());
//                if (matches) {
//                    String content = FileUtils.readFileToString(listFile, "utf-8");
//                    List<ExerciseVo> exercises = JSON.parseObject(content, new TypeReference<List<ExerciseVo>>() {
//                    });
//
//                    List<Exercise> saveExercise = exercises.stream()
//                            .peek(ExerciseVo::transform)
//                            .map(it -> {
//                        Exercise exercise = new Exercise();
//                        BeanUtils.copyProperties(it, exercise);
//                        return exercise;
//                    }).collect(Collectors.toList());
//                    exerciseService.saveBatch(saveExercise);
//
//                    exercises.stream().forEach(it->{
//                        List<Instruction> instructionList = it.getInstructionList();
//                        List<SecondaryMuscle> secondaryMuscleList = it.getSecondaryMuscleList();
//                        instructionService.saveBatch(instructionList);
//                        secondaryMucleService.saveBatch(secondaryMuscleList);
//                    });
//                }
//            }
//        }

        List<Exercise> exercises = exerciseService.list();
        for (Exercise exercise : exercises) {
            exercise.setGifUrl("http://192.168.2.4:7775/exercises/gift/" + exercise.getId());
            exerciseService.updateById(exercise);
        }
//        List<Instruction> instructions = instructionService.list();
//        List<SecondaryMuscle> sec = secondaryMucleService.list();
//        for (Instruction instruction : instructions) {
//            if (instruction.getContentCn() != null) {
//                continue;
//            }
//            System.out.println("翻译：" + instruction.getContent());
//            try {
//                instruction.setContentCn(BaiduTranslate.translate(instruction.getContent()));
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
////            TimeUnit.SECONDS.sleep(1);
//            instructionService.updateById(instruction);
//        }
//
//        Map<String, String> cache = new HashMap<>();
//
//        for (SecondaryMuscle secondaryMuscle : sec) {
//            if (secondaryMuscle.getContentCn() != null) {
//                continue;
//            }
//            System.out.println("翻译：" + secondaryMuscle.getContent());
//            try {
//                if (cache.containsKey(secondaryMuscle.getContent())) {
//                    secondaryMuscle.setContentCn(cache.get(secondaryMuscle.getContent()));
//                }else {
//                    secondaryMuscle.setContentCn(BaiduTranslate.translate(secondaryMuscle.getContent()));
//                    cache.put(secondaryMuscle.getContent(), secondaryMuscle.getContentCn());
//                }
//
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
////            TimeUnit.SECONDS.sleep(1);
//            secondaryMucleService.updateById(secondaryMuscle);
//        }

        return true;
    }

    @GetMapping("/gift/{exerciseId}")
    public void downloadGif(@PathVariable("exerciseId") String exerciseId,
                            HttpServletResponse response) {
        Exercise exercise = exerciseService.getById(exerciseId);
        byte[] giftBlob = exercise.getGiftBlob();
        try(
                OutputStream outputStream = response.getOutputStream();
        ){
            response.setContentType("image/gif");
            IOUtils.write(giftBlob, outputStream);
        }catch (IOException e) {
//            log.error("", e);
            e.printStackTrace();
            response.setStatus(404);
        }
    }
}
